#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP) // 不敢使用sizeof()
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP) // 不敢使用sizeof()

enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR
};

// "x op y"  -> "context_len"\r\n"x op y"\r\n
// "exitcode result"  -> "context_len"\r\n"exitcode result"\r\n
std::string enLength(const std::string &text)
{
    std::string send_string = std::to_string(text.size());
    send_string += LINE_SEP;
    send_string += text;
    send_string += LINE_SEP;

    return send_string;
}

// "context_len"\r\n"x op y"\r\n
bool deLength(const std::string &package, std::string *text)
{
    auto post = package.find(LINE_SEP);
    if (post == std::string::npos)
        return false;
    std::string context_len_string = package.substr(0, post);
    int context_len = std::stoi(context_len_string);

    *text = package.substr(post + LINE_SEP_LEN, context_len);
    return true;
}

// 没有人规定我们网络通信的时候，只能有一种协议！！
// 那怎么让昔日知道我们用的是哪一种协议呢？？
// "context_len"\r\n"协议编号"\r\n"x op y"\r\n
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char op) : _x(x), _y(y), _op(op)
    {
    }
    // 1.自己写
    // 2.用现成的
    bool serialize(std::string *out) // 序列化
    {
#ifdef MYSELF
        *out = ""; // 清空
        // 结构化 -> "x op y\r\n"
        std::string x_string = std::to_string(_x);
        std::string y_string = std::to_string(_y);

        *out = x_string;
        *out += SEP;
        *out += _op;
        *out += SEP;
        *out += y_string;
        // *out += LINE_SEP;
#else
        Json::Value root; // Json:Value:能接收万能类型的对象
        root["first"] = _x;
        root["second"] = _y;
        root["oper"] = _op;

        Json::FastWriter write;
        // Json::StyledWriter write;

        *out = write.write(root);
#endif
        return true;
    }
    bool deserialize(const std::string &in) // 反序列化
    {
#ifdef MYSELF
        // "x op y" -> 结构化
        auto left = in.find(SEP);
        auto right = in.rfind(SEP);
        if (left == std::string::npos || right == std::string::npos)
            return false;
        if (left == right)
            return false;
        if (((right - SEP_LEN) - left) != 1)
            return false;

        std::string x_string = in.substr(0, left);
        std::string y_string = in.substr(right + SEP_LEN);

        if (x_string.empty())
            return false;
        if (y_string.empty())
            return false;

        _x = std::stoi(x_string);
        _y = std::stoi(y_string);
        _op = in[left + SEP_LEN];
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        _x = root["first"].asInt();
        _y = root["second"].asInt();
        _op = root["oper"].asInt();

#endif
        return true;
        // auto pos = in.substr(0,)
    }

public:
    // "x op y"
    int _x;
    int _y;
    char _op;
};

class Response
{
public:
    Response() : exitcode(0), result(0)
    {
    }
    bool serialize(std::string *out) // 序列化
    {
#ifdef MYSELF
        *out = "";
        std::string ec_string = std::to_string(exitcode);
        std::string res_string = std::to_string(result);

        *out = ec_string;
        *out += SEP;
        *out += res_string;
#else
        Json::Value root;
        root["excode"] = exitcode;
        root["result"] = result;

        Json::FastWriter write;
        *out = write.write(root);
#endif
        return true;
    }
    bool deserialize(const std::string &in) // 反序列化
    {
#ifdef MYSELF
        // exitcode result
        auto mid = in.find(SEP);
        if (mid == std::string::npos)
            return false;
        std::string ec_string = in.substr(0, mid);
        std::string res_string = in.substr(mid + SEP_LEN);
        if (ec_string.empty() || res_string.empty())
            return false;

        exitcode = std::stoi(ec_string);
        result = std::stoi(res_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        exitcode = root["exitcode"].asInt();
        result = root["result"].asInt();
#endif
        return true;
    }

public:
    int exitcode; // 0计算成功，!0表示计算失败 协议自己定
    int result;   // 计算结果
};

// "context_len"\r\n"x op y"\r\n
bool recvRequest(int sock, std::string &inbuffer, std::string *text)
{
    char buffer[1024];
    while (true)
    {
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            inbuffer += buffer;
            // 分析处理
            auto post = inbuffer.find(LINE_SEP);
            if (post == std::string::npos)
                continue;
            std::string text_len_sting = inbuffer.substr(0, post);
            int text_len = std::stoi(text_len_sting);
            // "context_len"\r\n"x op y"\r\n  --> inbuffer.size() >= text_len_sting.size() + text_len + 2*LINE_SEP_LEN; 至少读到一个完整的报文
            int total_len = text_len_sting.size() + text_len + 2 * LINE_SEP_LEN;
            if (inbuffer.size() < total_len)
                continue;

            // 至少读到一个完整的报文
            *text = inbuffer.substr(0, total_len);
            inbuffer.erase(0, total_len);
            break;
        }
        else
            return false;
    }
    return true;
}